using Indiefreaks.AceOnSteroids.Entities;
using Indiefreaks.Xna.Input;
using Indiefreaks.Xna.Logic;
using Microsoft.Xna.Framework;

namespace Indiefreaks.AceOnSteroids.Logic.Behaviors
{
    /// <summary>
    /// The PlayerInputBehavior is a Behavior which Commands look for input events and apply these events to the attached SceneObject.
    /// In our case, the PlayerSpaceShip instance.
    /// </summary>
    public class PlayerInputBehavior : Behavior
    {
        /// <summary>
        /// Creates a new instance
        /// </summary>
        public PlayerInputBehavior()
        {
            // since we are developing a single player game, we'll use the AddLocalCommand method to add our commands but the pattern is the same to create multiplayer
            // commands except you'll need to define what happens locally, on the server and what is replicated on all clients.
            AddLocalCommand(ReadPlayerInput);
        }

        /// <summary>
        /// Reads player input and rotate and move the player spaceship
        /// </summary>
        /// <param name="command"/>
        /// <returns>Since this ClientCommand delegate is run locally only, it always return null</returns>
        /// <remarks>ClientCommand returned values are never processed so whatever you return it won't change anything to the game behavior</remarks>
        private object ReadPlayerInput(Command command)
        {
            // we retrieve the current player input
            PlayerInput playerInput = ((PlayerAgent) Agent).Input;

            // we need to retrieve the World matrix components to apply local rotation
            Vector3 scale;
            Quaternion rotation;
            Vector3 translation;
            Agent.ParentObject.World.Decompose(out scale, out rotation, out translation);

            if (playerInput.ThumbSticks.LeftStick.X < -0.3f)
            {
                // turn the spaceship left
                Agent.ParentObject.World = Matrix.CreateScale(scale)*Matrix.CreateFromQuaternion(rotation)*Matrix.CreateRotationY(0.1f)*Matrix.CreateTranslation(translation);
            }
            else if (playerInput.ThumbSticks.LeftStick.X > 0.3f)
            {
                // turn the spaceship right
                Agent.ParentObject.World = Matrix.CreateScale(scale)*Matrix.CreateFromQuaternion(rotation)*Matrix.CreateRotationY(-0.1f)*Matrix.CreateTranslation(translation);
            }

            if (playerInput.ThumbSticks.LeftStick.Y > 0.3f)
            {
                // activate spaceship engines
                // we'll use the physics system to apply our force to the spaceship. We'll use the leftstick (or virtual gamepad leftstick) forward to define the force.
                ((PlayerSpaceShip) Agent.ParentObject).CollisionMove.ApplyObjectForce(new Vector3(0f, 0f, playerInput.ThumbSticks.LeftStick.Y));
            }

            // the ClientCommand delegate requires you to return a value. This is useless on local only commands, but it lets you define what is the value that is automatically
            // transfered to the server so that it can get processed there. This is all automatic but we'll see that in a future video.
            // for now, we'll simply return null
            return null;
        }
    }
}